;; -------- switch themes based on sunrise/sunset time. --------
(defvar dark-theme "Hesperus")
(defvar light-theme "Phosphorus")
;; get sunrise and sunset times
(defun get-time-of-solar ()
  "Switch themes based on the local times of sunrise and sunset."
  (let* ((sslist (split-string (sunrise-sunset) "[:apm\s]")))
    (setq sunrise-time (string-to-number
			            (concat (nth 1 sslist) (nth 2 sslist))))
    (setq sunset-time (string-to-number
		               (concat (nth 7 sslist) (nth 8 sslist))))))
;; set default time without location
(if (or (null calendar-latitude)
	    (null calendar-longitude))
    (progn
      (setq sunrise-time 600)
      (setq sunset-time 1800))
  (get-time-of-solar))
;; compare with current time to confirm theme
(if (> (string-to-number (format-time-string "%H")) 12)
    (if (> (string-to-number (format-time-string "%I%M"))
	       sunset-time)
	    (setq my-current-theme light-theme)
      (setq my-current-theme dark-theme))
  (if (> (string-to-number (format-time-string "%H%M"))
	     sunrise-time)
      (setq my-current-theme dark-theme)
    (setq my-current-theme light-theme)))
;; function to switch between two themes
(defun p1uxtar-Switch-themes ()
  "Switch themes between Hesperus & Phosphorus."
  (interactive)
  (cond
   ((string-equal my-current-theme "Hesperus")
    (progn
      (disable-theme 'Hesperus)
      (load-theme 'Phosphorus t)
      (setq my-current-theme "Phosphorus")))
   ((string-equal my-current-theme "Phosphorus")
    (progn
      (disable-theme 'Phosphorus)
      (load-theme 'Hesperus t)
      (setq my-current-theme "Hesperus"))))
  (when (display-graphic-p)
    (awesome-tray-mode 1))
  (when (eq system-type 'windows-nt)
    (p1uxtar-Win-frame-size)))
;; set position
(setq calendar-latitude 34.49
	  calendar-longitude 113.32)
(global-set-key (kbd "C-c S") #'p1uxtar-Switch-themes)

;; -------- format code & prettier --------
(when (eq system-type 'gnu/linux)
  (use-package format-all
    :defer t
    :diminish format-all-mode
    ;; :hook
    ;; ((prog-mode) . format-all-mode)
    :config
    (format-all-mode)
    :bind
    (("C-S-f" . 'format-all-buffer))))

(use-package prettier
  :init
  (setenv "NODE_PATH" "/usr/lib/node_modules")
  :hook
  ((after-init) . global-prettier-mode)
  :config
  (defun p1uxtar-prettier ()
    (interactive)
    (shell-command
     (format "%s --write %s"
	         (shell-quote-argument (executable-find "prettier"))
	         (shell-quote-argument (expand-file-name buffer-file-name))))
    (revert-buffer t t t))
  (add-hook 'markdown-mode-hook
	        (lambda ()
		      (add-hook 'after-save-hook 'p1uxtar-prettier t t))))

(use-package shfmt
  :config
  (add-hook 'sh-mode-hook 'shfmt-on-save-mode))

;; -------- three functions to format R code --------
(defun p1uxtar-ess-indent-region-as-r (beg end)
  "Format region of code R using the R parser."
  (interactive "r")
  (let ((string (replace-regexp-in-string
		         "\"" "\\\\\\&"
		         (replace-regexp-in-string ;; how to avoid this double matching?
		          "\\\\\"" "\\\\\\&" (buffer-substring-no-properties beg end))))
	    (buf (get-buffer-create "*ess-command-output*")))
    (ess-force-buffer-current "Process to load into:")
    (ess-command
     (format
	  "local({oo <- options(keep.source = FALSE);
cat('\n', paste(deparse(parse(text = \"%s\")[[1L]]), collapse = '\n'), '\n', sep = '')
options(oo)})\n"
	  string) buf)
    (with-current-buffer buf
	  (goto-char (point-max))
	  ;; (skip-chars-backward "\n")
	  (let ((end (point)))
	    (goto-char (point-min))
	    (goto-char (1+ (point-at-eol)))
	    (setq string (buffer-substring-no-properties (point) end))
	    ))
    (delete-region beg end)
    (insert string)
    ))

(defun p1uxtar-ess-indent-region-with-formatR (beg end)
  "Format region of code R using formatR::tidy_source()."
  (interactive "r")
  (let ((string
	     (replace-regexp-in-string
	      "\"" "\\\\\\&"
	      (replace-regexp-in-string ;; how to avoid this double matching?
	       "\\\\\"" "\\\\\\&"
	       (buffer-substring-no-properties beg end))))
	    (buf (get-buffer-create "*ess-command-output*")))
    (ess-force-buffer-current "Process to load into:")
    (ess-command
     (format                            ; R parser use 'width.cutoff = 60L'
	  "local({formatR::tidy_source(text = \"\n%s\", arrow = TRUE, width.cutoff = 60L) })\n"
	  string) buf)
    (with-current-buffer buf
	  (goto-char (point-max))
	  ;; (skip-chars-backward "\n")
	  (let ((end (point)))
	    (goto-char (point-min))
	    (goto-char (1+ (point-at-eol)))
	    (setq string (buffer-substring-no-properties (point) end))
	    ))
    (delete-region beg end)
    (insert string)
    (delete-char -1)
    ))

(defun p1uxtar-ess-indent-region-with-styler (beg end)
  "Format region of code R using styler::style_text()."
  (interactive "r")
  (let ((string
	     (replace-regexp-in-string
	      "\"" "\\\\\\&"
	      (replace-regexp-in-string ;; how to avoid this double matching?
	       "\\\\\"" "\\\\\\&"
	       (buffer-substring-no-properties beg end))))
	    (buf (get-buffer-create "*ess-command-output*")))
    (ess-force-buffer-current "Process to load into:")
    (ess-command
     (format
	  "local({options(styler.colored_print.vertical = FALSE);styler::style_text(text = \"\n%s\", reindention = styler::specify_reindention(regex_pattern = \"###\", indention = 0), indent_by = 4)})\n"
	  string) buf)
    (with-current-buffer buf
	  (goto-char (point-max))
	  ;; (skip-chars-backward "\n")
	  (let ((end (point)))
	    (goto-char (point-min))
	    (goto-char (1+ (point-at-eol)))
	    (setq string (buffer-substring-no-properties (point) end))
	    ))
    (delete-region beg end)
    (insert string)
    (delete-char -1)
    ))

;; -------- line number --------
(with-eval-after-load 'linum
  '(progn
     (defface linum-leading-zero
       `((t :inherit 'linum
            :foreground ,(face-attribute 'linum :background nil t)))
       "Face for displaying leading zeroes for line numbers in display margin."
       :group 'linum)
     (defun linum-format-func (line)
       (let ((w (length
                 (number-to-string (count-lines (point-min) (point-max))))))
         (concat
          (propertize (make-string (- w (length (number-to-string line))) ?0)
                      'face 'linum-leading-zero)
          (propertize (number-to-string line) 'face 'linum)
          ;; (propertize " ")
          )))
     (setq linum-format 'linum-format-func)))

;; -------- all-the-icons --------
(use-package all-the-icons
  :config
  (declare-function memoize 'memoize)
  (declare-function memoize-restore 'memoize)
  (defun all-the-icons-reset ()
    "Reset (unmemoize/memoize) the icons."
    (interactive)
    (ignore-errors
      (dolist (f '(all-the-icons-icon-for-file
                   all-the-icons-icon-for-mode
                   all-the-icons-icon-for-url
                   all-the-icons-icon-family-for-file
                   all-the-icons-icon-family-for-mode
                   all-the-icons-icon-family))
        (memoize-restore f)
        (memoize f)))
    (message "Reset all-the-icons"))
  (add-to-list 'all-the-icons-icon-alist
               '("^Rakefile$" all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.go$" all-the-icons-fileicon "go" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\go.mod$" all-the-icons-fileicon "go" :face all-the-icons-dblue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\go.sum$" all-the-icons-fileicon "go" :face all-the-icons-dpurple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(go-mode all-the-icons-fileicon "go" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(xwidget-webkit-mode all-the-icons-faicon "chrome" :v-adjust -0.1 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(bongo-playlist-mode all-the-icons-material "playlist_play" :height 1.2 :v-adjust -0.2 :face 'all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(bongo-library-mode all-the-icons-material "library_music" :height 1.1 :v-adjust -0.2 :face 'all-the-icons-dgreen))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-group-mode all-the-icons-fileicon "gnu" :face 'all-the-icons-silver))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-summary-mode all-the-icons-octicon "inbox" :height 1.0 :v-adjust 0.0 :face 'all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-article-mode all-the-icons-octicon "mail" :height 1.1 :v-adjust 0.0 :face 'all-the-icons-lblue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(message-mode all-the-icons-octicon "mail" :height 1.1 :v-adjust 0.0 :face 'all-the-icons-lblue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(diff-mode all-the-icons-octicon "git-compare" :v-adjust 0.0 :face all-the-icons-lred))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(flycheck-error-list-mode all-the-icons-octicon "checklist" :height 1.1 :v-adjust 0.0 :face all-the-icons-lred))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.rss$" all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(elfeed-search-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(elfeed-show-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-list-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-item-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.[bB][iI][nN]$" all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.c?make$" all-the-icons-fileicon "gnu" :face all-the-icons-dorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.conf$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.toml$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(conf-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(conf-space-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(forge-topic-mode all-the-icons-alltheicon "git" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.xpm$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-dgreen))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(help-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1 :face all-the-icons-purple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(helpful-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1 :face all-the-icons-purple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(Info-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1))
  (add-to-list 'all-the-icons-icon-alist
               '("NEWS$" all-the-icons-faicon "newspaper-o" :height 0.9 :v-adjust -0.2))
  (add-to-list 'all-the-icons-icon-alist
               '("Cask\\'" all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(cask-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '(".*\\.ipynb\\'" all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebooklist-mode all-the-icons-faicon "book" :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebook-mode all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebook-multilang-mode all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-dorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.epub\\'" all-the-icons-faicon "book" :height 1.0 :v-adjust -0.1 :face all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(nov-mode all-the-icons-faicon "book" :height 1.0 :v-adjust -0.1 :face all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gfm-mode all-the-icons-octicon "markdown" :face all-the-icons-lblue)))

;; -------- fade cursor to highlight --------
(use-package beacon
  :defer t
  :diminish beacon-mode
  :config
  (setq beacon-color (face-attribute 'highlight :background))
  (beacon-mode 1))

;; ;; -------- highlight-indentation --------
(use-package highlight-indentation
  :defer t
  :diminish highlight-indentation-mode
  :hook
  ((prog-mode) . highlight-indentation-mode))

;; -------- highlight-indent-guides --------
(use-package highlight-indent-guides
  :diminish highlight-indent-guides-mode
  :hook
  ((prog-mode) . highlight-indent-guides-mode)
  :init
  (setq highlight-indent-guides-method 'column
	    highlight-indent-guides-auto-enabled t
	    highlight-indent-guides-responsive 'top))

;; -------- R --------
;; display *R* buffer
(setq display-buffer-alist
      `(("*R"
         (display-buffer-reuse-window display-buffer-in-side-window)
         (side . right)
         (slot . -1)
         (window-width . 0.5)
         (reusable-frames . nil))
        ;; ("*Help"
        ;;  (display-buffer-reuse-window display-buffer-at-bottom)
        ;;  (window-width . 0.5)
        ;;  (reusable-frames . nil))
        ("\\.R$"
         (display-buffer-reuse-window display-buffer-in-side-window)
         (side . left)
         (slot . 1)
         (window-width . 0.5)
         (reusable-frames . nil))))

;; highlight R functions etc.
(setq inferior-R-font-lock-keywords
      '((ess-S-fl-keyword:prompt . t)
        (ess-R-fl-keyword:messages . t)
        (ess-R-fl-keyword:modifiers . t)
        (ess-R-fl-keyword:fun-defs . t)
        (ess-R-fl-keyword:keywords . t)
        (ess-R-fl-keyword:assign-ops . t)
        (ess-R-fl-keyword:constants . t)
        (ess-fl-keyword:matrix-labels . t)
        (ess-fl-keyword:fun-calls . t)
        (ess-fl-keyword:numbers . t)
        (ess-fl-keyword:operators . t)
        (ess-fl-keyword:delimiters . t)
        (ess-fl-keyword:= . t)
        (ess-R-fl-keyword:F&T . t)
        (ess-R-fl-keyword:%op% . t)
        ))
